#pragma once
/*--------------------------------------------------------------------------------
 * Adaptive Intelligence - Foundation Framework Class Library
 * Version 2.00
 * 
 * Sockets Daemon Class
 *      Provides a sockets daemon (listener) instance for accepting incoming
 * connections.
 *------------------------------------------------------------------------------*/

/*--------------------------------------------------------------------------------
 * System Imports
 *------------------------------------------------------------------------------*/
#include "stdafx.h"
#include "SafeSocketHandle.h"
#include "SocketsConnection.h"
#include "SocketsConnectionManager.h"

using namespace System;
using namespace System::Net;
using namespace System::Net::Sockets;
using namespace System::Threading;
using namespace Adaptive;
using namespace Adaptive::Foundation;

namespace Adaptive
{
	namespace Network
	{
		namespace Sockets
		{
			/// <summary>
			/// Provides a sockets daemon (listener) instance for accepting incoming connections.
			/// </summary>
			public ref class SocketsDaemon : public DisposableObjectBase
			{
			public:
				/*--------------------------------------------------------------------------------
				 * Public Event Declarations
				 *------------------------------------------------------------------------------*/
				#pragma region Public Event Declarations
				/// <summary>
				/// Occurs when a new connection is requested.
				/// </summary>
				event ConnectionRequestEventHandler^ ConnectionRequest;
				/// <summary>
				/// Occurs when a new connection is established.
				/// </summary>
				event ConnectionEventHandler^ Connection;
				/// <summary>
				/// Occurs when a socket error/exception is encountered.
				/// </summary>
				event SocketErrorEventHandler^ SocketException;
				#pragma endregion
				
				/*--------------------------------------------------------------------------------
				 * Constructor / Dispose / Destructor Methods
				 *------------------------------------------------------------------------------*/
				#pragma region Constructor / Dispose / Destructor Methods
				/// <summary>
				/// Initializes a new instance of the class.
				/// </summary>
				/// <remarks>
				/// This is the default constructor.
				/// </remarks>
				SocketsDaemon();
				/// <summary>
				/// Class destructor.
				/// </summary>
				~SocketsDaemon();
				/// <summary>
				/// Class destructor.
				/// </summary>
				!SocketsDaemon();
				#pragma endregion
				
				/*--------------------------------------------------------------------------------
				 * Public Properties
				 *------------------------------------------------------------------------------*/
				#pragma region Public Properties
				/// <summary>
				/// Gets the reference to the connection manager instance.
				/// </summary>
				/// <value>
				/// A <see cref="SocketsConnectionManager"/> instance used 
				/// to contain and manage all the established sockets connections.
				/// </value>
				property SocketsConnectionManager^ ConnectionManager { SocketsConnectionManager^ get(); }
				/// <summary>
				/// Gets the ID of the object instance.
				/// </summary>
				/// <value>
				/// The socket handle as a string, or <b>null</b> if not assigned.
				/// </value>
				property String^ Id { String^ get(); }
				/// <summary>
				/// Gets a value indicating whether the object is currently listening for new connections.
				/// </summary>
				/// <value>
				/// <b>true</b> if currently listening; otherwise, <b>false</b>.
				/// </value>
				property bool IsListening { bool get(); }
				/// <summary>
				/// Gets or sets the maximum number of connections that are allowed.
				/// </summary>
				/// <value>
				/// The maximum number of socket connections that may be accept()ed and active at one time.
				/// </value>
				property int MaxConnections { int get(); void set( int value); }
				/// <summary>
				/// Gets or sets the local address and port number to bind to.
				/// </summary>
				/// <value>
				/// An <see cref="IPEndPoint"/> instance used to define the binding on which the 
				/// daemon will listen for connections.
				/// </value>
				/// <remarks>
				/// This property may not be set when the daemon is listening.
				/// </remarks>
				property IPEndPoint^ LocalEndPoint { IPEndPoint^ get(); void set(IPEndPoint^ endPoint); }
				#pragma endregion
				
				/*--------------------------------------------------------------------------------
				 * Public Methods / Functions
				 *------------------------------------------------------------------------------*/
				#pragma region Public Methods / Functions
				/// <summary>
				/// Listens for new socket connections on the specified address binding.
				/// </summary>
				/// <param name="endPoint">
				/// An <see cref="IPEndPoint"/> instance used to define the binding on which the 
				/// daemon will listen for connections.
				/// </param>
				/// <returns>
				/// <b>true</b> if the action is successful and the daemon is listening; otherwise,
				/// <b>false</b>.
				/// </returns>
				bool Listen(IPEndPoint^ endPoint);
				/// <summary>
				/// Listens for new socket connections on the specified address binding.
				/// </summary>
				/// <returns>
				/// <b>true</b> if the action is successful and the daemon is listening; otherwise,
				/// <b>false</b>.
				/// </returns>
				bool Listen();
				/// <summary>
				/// Stops the listener from listening for and accepting new connections.
				/// </summary>
				/// <remarks>
				/// Any active <see cref="SocketsConnection"/> instances will continue to execute as normal
				/// event when the listener is stopped.
				/// </remarks>
				void StopListening();
				/// <summary>
				/// Stops the listener from listening for and accepting new connections, and terminates
				/// all current activity.
				/// </summary>
				/// <param name="closeGracefully">
				/// When set to <b>true</b>, the method will wait for each individual socket connection 
				/// instance to close and return before destroying the object.  When set to <b>false</b>, 
				/// the method will destroy all <see cref="SocketsConnection"/> instances in the 
				/// <see cref="ConnectionManager"/> instance as quickly as possible without regard to gracefully
				/// closing any existing socket connections.
				/// </param>
				/// <remarks>
				/// This method is used to stop the listener socket from listening and accepting new connections,
				/// as well as to close all existing <see cref="SocketsConnection"/> connections currently in the 
				/// <see cref="ConnectionManager"/> instance.
				///
				/// This method will block until all sockets are closed/terminated.  
				/// </remarks>
				void ShutdownActivity(bool closeGracefully);
				#pragma endregion
				
			protected:

				/*--------------------------------------------------------------------------------
				 * Event Methods
				 *------------------------------------------------------------------------------*/
				#pragma region Event Methods
				/// <summary>
				/// Raises the <see cref="ConnectionRequest"/> event.
				/// </summary> 
				/// <param name="e">
				/// A <see cref="ConnectionRequestEventArgs"/> event arguments instance.
				/// </param>
				virtual void OnConnectionRequest(ConnectionRequestEventArgs^ e);
				/// <summary>
				/// Raises the <see cref="Connection"/> event.
				/// </summary> 
				/// <param name="e">
				/// A <see cref="ConnectionEventArgs"/> event arguments instance.
				/// </param>
				virtual void OnConnection(ConnectionEventArgs^ e);
				/// <summary>
				/// Raises the <see cref="SocketException"/> event.
				/// </summary> 
				/// <param name="e">
				/// A <see cref="SocketErrorEventArgs"/> event arguments instance.
				/// </param>
				virtual void OnSocketException(SocketErrorEventArgs^ e);
				#pragma endregion
				
				/*--------------------------------------------------------------------------------
				 * Protected Methods / Functions
				 *------------------------------------------------------------------------------*/
				#pragma region Protected Methods / Functions
				#pragma endregion
				
			private:
				/*--------------------------------------------------------------------------------
				 * Private Member Declarations
				 *------------------------------------------------------------------------------*/
				#pragma region Private Member Declarations

				SafeSocketHandle^			_listenerSocket;
				SocketsConnectionManager^	_connectionManager;
				Thread^						_connectionPollThread;
				IPEndPoint^					_localEndPoint;

				bool						_executeFlag;
				int							_maxConnections;
				#pragma endregion
				
				/*--------------------------------------------------------------------------------
				 * Private Methods / Functions
				 *------------------------------------------------------------------------------*/
				#pragma region Private Methods / Functions

				void LaunchPollingThread();
				void ExecutePollingThread();
				void TerminatePollingThread();
				void AsyncTerminatePollingThread();
				void LaunchConnectionRequestThread(SafeSocketHandle^ newSocketInstance);
				void ExecuteConnectionRequestThread(Object^ newSocketInstance);
				
				#pragma endregion
				
			};
		}
	}
}